/*******************************************************************************
 * Copyright (c) 2010 L.Carbonnaux.
 *******************************************************************************/

package org.lcx.taskvision.ui.wizzard;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.core.ITask.PriorityLevel;
import org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositoryQueryPage;
import org.eclipse.swt.SWT;

import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Text;
import org.lcx.taskvision.core.ITaskVisionClient;
import org.lcx.taskvision.core.attribute.TaskVisionAttribute;
import org.lcx.taskvision.core.model.TaskVisionQueryOption;

/**
 * @author Laurent Carbonnaux
 */
public class TaskVisionQueryWizardPage extends AbstractRepositoryQueryPage {

	private static final String PAGE_TITLE = Messages.ScrumVisionQueryWizzard_page_title;

	private static final String DESCRIPTION = Messages.ScrumVisionQueryWizzard_page_description;
	
	private IRepositoryQuery originalQuery = null;

	private boolean firstTime = true;	

	private Composite tagsgroup;
	
	private Text titleText;
	
	private List priorityTag;
	private Label priorityLabel;

	private java.util.List<Button> completedTags = new ArrayList<Button>();

	private StringFieldEditor summary;
	private StringFieldEditor description;
	
	
	private final class ModifyListenerImplementation implements ModifyListener {
		public void modifyText(ModifyEvent e) {
			if (isControlCreated()) {
				setPageComplete(isPageComplete());
			}
		}
	}

	public TaskVisionQueryWizardPage(TaskRepository taskRepository, IRepositoryQuery query) {
		super(PAGE_TITLE, taskRepository, query);
		setTitle(PAGE_TITLE);
		setDescription(DESCRIPTION);
		originalQuery = query;
	}
	
	public void createControl(Composite control) {
		final Composite composite = new Composite(control, SWT.NONE);
		composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
		final GridLayout gridLayout = new GridLayout();
		gridLayout.marginBottom = 8;
		gridLayout.marginHeight = 0;
		gridLayout.marginWidth = 0;
		gridLayout.numColumns = 2;
		composite.setLayout(gridLayout);

		createTitleGroup(composite);
		
		createTagsGroup(composite);

		Button resetButton = new Button(composite, SWT.PUSH);
		resetButton.setText(Messages.ScrumVisionQueryWizzard_reset_selection);
		resetButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
		resetButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				resetSelection();
			}
		});
		
		setPageComplete(isPageComplete());
		setControl(control);
	}

	private void createTitleGroup(Composite composite){
		if (!inSearchContainer()) {
			final Label queryTitleLabel = new Label(composite, SWT.NONE);
			queryTitleLabel.setText(Messages.ScrumVisionQueryWizzard_query_title);

			titleText = new Text(composite, SWT.BORDER);
			titleText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
			if (originalQuery != null) {
				titleText.setText(originalQuery.getSummary());
			}
			titleText.addModifyListener(new ModifyListenerImplementation());
			titleText.setFocus();
		}		
	}

	private void createTagsGroup(Composite parent){
	
			tagsgroup = new Composite(parent, SWT.NONE);
			tagsgroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
			final GridLayout gridLayout = new GridLayout();
			gridLayout.marginBottom = 8;
			gridLayout.marginHeight = 0;
			gridLayout.marginWidth = 0;
			gridLayout.numColumns = 2;
			tagsgroup.setLayout(gridLayout);

			summary = new StringFieldEditor("", Messages.ScrumVisionQueryWizzard_summary, 
					StringFieldEditor.UNLIMITED,
					tagsgroup);
			
			description = new StringFieldEditor("", Messages.ScrumVisionQueryWizzard_description, 
					StringFieldEditor.UNLIMITED,
					tagsgroup);
			
			final Label completedLabel = new Label(tagsgroup, SWT.NONE);
			completedLabel.setText(Messages.ScrumVisionQueryWizzard_completed);
			this.createCompletedGroup(tagsgroup);
			
			priorityLabel = new Label(tagsgroup, SWT.NONE);
			priorityLabel.setText(Messages.ScrumVisionQueryWizzard_priority);
	
			priorityTag = new List(tagsgroup, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER);
			priorityTag.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
			initPriotityTag();
		}
	
	private void createCompletedGroup(Composite parent){
		
		Composite queryTypegroup = new Composite(parent, SWT.NONE);
		queryTypegroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		final GridLayout gridLayout = new GridLayout();
		gridLayout.marginBottom = 8;
		gridLayout.marginHeight = 0;
		gridLayout.marginWidth = 0;
		gridLayout.numColumns = 3;
		queryTypegroup.setLayout(gridLayout);
		
			Button but = new Button(queryTypegroup, SWT.RADIO);
			completedTags.add(but);
			but.setLayoutData(new GridData(SWT.NONE, SWT.CENTER, false, false));
			but.setText(Messages.ScrumVisionQueryWizzard_completed_all);
			but.setSelection(true);

			but = new Button(queryTypegroup, SWT.RADIO);
			completedTags.add(but);
			but.setLayoutData(new GridData(SWT.NONE, SWT.CENTER, false, false));
			but.setText(Messages.ScrumVisionQueryWizzard_completed_false);
			
			but = new Button(queryTypegroup, SWT.RADIO);
			completedTags.add(but);
			but.setLayoutData(new GridData(SWT.NONE, SWT.CENTER, false, false));
			but.setText(Messages.ScrumVisionQueryWizzard_completed_true);
			
	}

	private String validatePage() {
		String message = null;
		if (titleText != null && titleText.getText().trim().length() == 0) {
			message = Messages.ScrumVisionQueryWizzard_title_Error;
		}
		return message;
	}
	
	@Override
	public boolean isPageComplete() {
		String errorMessage = null;

		errorMessage = validatePage();
		
		setErrorMessage(errorMessage);
		return getErrorMessage() == null;
		
	}

	private String constructQuery(){

		StringBuffer buff = new StringBuffer();
		buff.append(ITaskVisionClient.ALL_TASKS_QUERY);
		buff.append(constructQueryForTagString(TaskVisionAttribute.SUMMARY.getSvKey(), summary));
		buff.append(constructQueryForTagString(TaskVisionAttribute.DESCRIPTION.getSvKey(), description));
		buff.append(constructQueryForTagListPriority(TaskVisionAttribute.PRIORITY.getSvKey(), priorityTag));
		buff.append(constructQueryForTagCompleted(TaskVisionAttribute.COMPLETED.getSvKey(), completedTags));
		return buff.toString();
	}

	private String constructQueryForTagCompleted(String tag, java.util.List<Button> completedTags){
		StringBuffer buff = new StringBuffer();
		for (Button button : completedTags) {
			if(button.getSelection()) {
				if(button.getText().equals(Messages.ScrumVisionQueryWizzard_completed_true)) {
					buff.append(ITaskVisionClient.QUERY_AND+"(");
					buff.append(tag+"!=\"\"");
					buff.append(")");
				} else if (button.getText().equals(Messages.ScrumVisionQueryWizzard_completed_false)) {
					buff.append(ITaskVisionClient.QUERY_AND+"(");
					buff.append(tag+"=\"\"");
					buff.append(")");
				}
			}
		}
		return buff.toString();
	}

	private String constructQueryForTagListPriority(String tag, List list){
		StringBuffer buff = new StringBuffer();
		if(list.getSelectionCount()!=0){
			buff.append(ITaskVisionClient.QUERY_AND+"(");
			for (int i = 0; i < list.getSelection().length; i++) {
				if(i!=0) buff.append(ITaskVisionClient.QUERY_OR);
				String sprio = list.getSelection()[i];
				buff.append(tag+"=\""+sprio+"\"");
			}
			buff.append(")");
		}
		return buff.toString();
	}
	
	private String constructQueryForTagString(String tag, StringFieldEditor field){
		StringBuffer buff = new StringBuffer();
		String value = field.getStringValue();
		if(value!=null && value.trim().length()>0){
			buff.append(ITaskVisionClient.QUERY_AND+"(");
				buff.append(tag+"=\""+value+"\"");
			buff.append(")");
		}
		return buff.toString();
	}
	
	private java.util.List<TaskVisionQueryOption> destructQueryForTag(String originalQuery){
		java.util.List<TaskVisionQueryOption> listTags = new ArrayList<TaskVisionQueryOption>();
		Map<String, TaskVisionQueryOption> mapTags = new HashMap<String, TaskVisionQueryOption>();

		String query = originalQuery.substring(ITaskVisionClient.ALL_TASKS_QUERY.length());
		
		query = query.replace('(', ' ');
		query = query.replace(')', ' ');
		query = query.replace(ITaskVisionClient.QUERY_AND, "#");
		query = query.replace(ITaskVisionClient.QUERY_OR, "#");
		
		String[] groupAnds = query.split("#");
		for (String groupOption : groupAnds) {
			if (groupOption.length()==0) continue;
				String[] tags = groupOption.split("=");
				String tag = null;
				String value = null;
				boolean negative=false;
				for (int i = 0; i < tags.length; i++) {
					if((i%2) == 0){
						tag = tags[i].trim();
						if(tag.endsWith("!")){ 
							tag = tag.substring(0, tag.length()-1);
							negative=true;
						}
					} else {
						value = tags[i].trim();
						if(tag!=null && value !=null){
							TaskVisionQueryOption qo = mapTags.get(tag);
							if(qo==null){
								qo = new TaskVisionQueryOption(tag);
								listTags.add(qo);
							}
							qo.addValue(value.substring(1, value.length() -1));
							qo.setNegative(negative);
							mapTags.put(tag, qo);
						}
						tag=null;
						value=null;
					}

				}
		}
		return listTags;
	}	
	
	public void setVisible(boolean visible) {
		if (visible) {
			if (firstTime) {
				firstTime = false;

				if (originalQuery != null) {
//					initPriotityTag();
					resetSelection();
					for(Button but : completedTags) {
						but.setSelection(false);
					}
					updateSelectedFromQuery(originalQuery.getUrl());
				}
			}
			
			setPageComplete(isPageComplete());
		}
		super.setVisible(visible);
	}
	
	private void updateSelectedFromQuery(String queryUrl) {
		java.util.List<TaskVisionQueryOption> listTags = destructQueryForTag(queryUrl);
		completedTags.get(0).setSelection(true);
		for (TaskVisionQueryOption qo : listTags) {
			String tag = qo.getTag();
			if (tag.equals(TaskVisionAttribute.PRIORITY.getSvKey())){
				fillTagPriority(priorityTag, qo.getListValues());
			} else if (tag.equals(TaskVisionAttribute.COMPLETED.getSvKey())){
				if(qo.getListValues().size()>0) {
					if(qo.getListValues().get(0).equals("") && qo.isNegative())
						completedTags.get(2).setSelection(true);
					else 
						completedTags.get(1).setSelection(true);
					completedTags.get(0).setSelection(false);
				}
			} else if (tag.equals(TaskVisionAttribute.SUMMARY.getSvKey())){
				if(qo.getListValues().size()>0) {
					summary.setStringValue(qo.getListValues().get(0));
				}
			} else if (tag.equals(TaskVisionAttribute.DESCRIPTION.getSvKey())){
				if(qo.getListValues().size()>0) {
					description.setStringValue(qo.getListValues().get(0));
				}
			}

		}

	}

	private void fillTagPriority(List widget, ArrayList<String> listValues){
		String[] sel = widget.getSelection();
		java.util.List<String> selList = Arrays.asList(sel);
		selList = new ArrayList<String>(selList);
		for (String value : listValues) {
			selList.add(value);
		}
		sel = new String[selList.size()];
		widget.setSelection(selList.toArray(sel));
	}

	private void initPriotityTag() {
		for (int i = 0; i < PriorityLevel.values().length; i++) {
			PriorityLevel p = PriorityLevel.values()[i];
			priorityTag.add(p.toString());
		}
	}

	private void resetSelection() {
		priorityTag.deselectAll();
		summary.setStringValue("");
		description.setStringValue("");
		for(Button but : completedTags) {
			but.setSelection(false);
		}
		completedTags.get(0).setSelection(true);
	}	
	
	@Override
	public void applyTo(IRepositoryQuery query) {
//		savePreferences();
		query.setUrl(constructQuery());
		query.setSummary(getQueryTitle());
	}

	@Override
	public String getQueryTitle() {
		return (titleText != null) ? titleText.getText() : null;
	}

}
